import tkinter as tk
from tkinter import filedialog, ttk, messagebox, scrolledtext
import os
import pathlib
import re

class ImageRenamerApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("图片批量重命名工具")
        self.geometry("1000x700")
        self.minsize(800, 600)
        
        # 设置字体和样式
        self.style = ttk.Style()
        self.style.configure("TButton", font=("微软雅黑", 10))
        self.style.configure("TLabel", font=("微软雅黑", 10))
        self.style.configure("Header.TLabel", font=("微软雅黑", 12, "bold"))
        self.style.configure("DragArea.TFrame", background="#f0f0f0", borderwidth=2, relief="groove")
        
        # 创建主框架
        self.main_frame = ttk.Frame(self, padding="20")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        ttk.Label(
            self.main_frame, 
            text="图片批量重命名工具", 
            style="Header.TLabel"
        ).pack(pady=(0, 20))
        
        # 创建三个功能区域的容器
        self.areas_frame = ttk.Frame(self.main_frame)
        self.areas_frame.pack(fill=tk.BOTH, expand=True)
        
        # 设置列权重，使三个区域平均分配空间
        for i in range(3):
            self.areas_frame.grid_columnconfigure(i, weight=1)
        self.areas_frame.grid_rowconfigure(0, weight=1)
        
        # 主图区域
        self.main_area = self.create_function_area(
            "主图处理区", 
            "Main", 
            ["主", "图", "首"],
            0
        )
        
        # 详情图区域
        self.detail_area = self.create_function_area(
            "详情图处理区", 
            "Detail", 
            ["详情", "长图"],
            1
        )
        
        # SKU图区域
        self.sku_area = self.create_function_area(
            "SKU图处理区", 
            "SKU", 
            ["规格", "属性"],
            2
        )
    
    def create_function_area(self, title, prefix, replace_words, column):
        """创建一个功能区域"""
        frame = ttk.Frame(self.areas_frame, padding="10")
        frame.grid(row=0, column=column, padx=10, pady=5, sticky="nsew")
        
        # 区域标题
        ttk.Label(frame, text=title, style="Header.TLabel").pack(pady=(0, 10))
        
        # 选择区域
        select_frame = ttk.Frame(frame, style="DragArea.TFrame", padding="10")
        select_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        # 选择提示
        select_label = ttk.Label(
            select_frame, 
            text="点击下方按钮选择文件夹",
            justify=tk.CENTER
        )
        select_label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
        
        # 按钮区域
        btn_frame = ttk.Frame(frame)
        btn_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 选择文件夹按钮
        select_btn = ttk.Button(
            btn_frame, 
            text="选择文件夹", 
            command=lambda p=prefix, r=replace_words, f=select_frame, sl=select_label: 
                       self.select_folder(p, r, f, sl)
        )
        select_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 处理按钮
        process_btn = ttk.Button(
            btn_frame, 
            text="开始重命名", 
            command=lambda p=prefix, r=replace_words, f=select_frame, sl=select_label: 
                       self.process_files_in_area(p, r, f, sl)
        )
        process_btn.pack(side=tk.LEFT)
        
        # 进度条
        progress_var = tk.DoubleVar()
        progress_bar = ttk.Progressbar(
            frame, 
            variable=progress_var, 
            length=100, 
            mode='determinate'
        )
        progress_bar.pack(fill=tk.X, pady=(0, 10))
        
        # 状态标签
        status_label = ttk.Label(frame, text="等待操作...", foreground="blue")
        status_label.pack(anchor=tk.W, pady=(0, 10))
        
        # 日志区域
        ttk.Label(frame, text="操作日志:").pack(anchor=tk.W)
        
        log_text = scrolledtext.ScrolledText(
            frame, 
            wrap=tk.WORD, 
            height=6,
            font=("微软雅黑", 9)
        )
        log_text.pack(fill=tk.BOTH, expand=True)
        log_text.config(state=tk.DISABLED)
        
        # 存储区域的相关组件，便于后续操作
        area_data = {
            "select_frame": select_frame,
            "select_label": select_label,
            "progress_var": progress_var,
            "progress_bar": progress_bar,
            "status_label": status_label,
            "log_text": log_text,
            "selected_path": None,
            "prefix": prefix,
            "replace_words": replace_words
        }
        
        return area_data
    
    def log_to_area(self, area_data, message):
        """向指定区域的日志文本框添加消息"""
        log_text = area_data["log_text"]
        log_text.config(state=tk.NORMAL)
        log_text.insert(tk.END, message + "\n")
        log_text.see(tk.END)  # 滚动到最后
        log_text.config(state=tk.DISABLED)
        self.update_idletasks()  # 更新界面
    
    def update_area_status(self, area_data, message):
        """更新指定区域的状态标签"""
        area_data["status_label"].config(text=message)
        self.update_idletasks()
    
    def update_area_progress(self, area_data, value):
        """更新指定区域的进度条"""
        area_data["progress_var"].set(value)
        self.update_idletasks()
    
    def select_folder(self, prefix, replace_words, select_frame, select_label):
        """选择文件夹并处理"""
        # 找到对应的区域数据
        area_data = self.find_area_data_by_select_frame(select_frame)
        if not area_data:
            return
            
        folder_path = filedialog.askdirectory(
            initialdir=os.getcwd(),
            title=f"选择{area_data['status_label']['text'].split('处理区')[0]}文件夹"
        )
        
        if folder_path:
            self.set_area_selected_path(area_data, folder_path)
    
    def set_area_selected_path(self, area_data, path):
        """设置区域选中的路径并更新显示"""
        area_data["selected_path"] = path
        area_data["select_label"].config(text=f"已选择:\n{os.path.basename(path)}")
        self.update_area_status(area_data, f"已选择文件夹: {os.path.basename(path)}")
        self.log_to_area(area_data, f"已选择文件夹: {path}")
    
    def find_area_data_by_select_frame(self, select_frame):
        """通过选择框架找到对应的区域数据"""
        for area in [self.main_area, self.detail_area, self.sku_area]:
            if area["select_frame"] == select_frame:
                return area
        return None
    
    def get_image_files(self, folder_path):
        """获取文件夹中的所有图片文件"""
        image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.webp'}
        image_files = []
        
        for filename in os.listdir(folder_path):
            file_path = os.path.join(folder_path, filename)
            if os.path.isfile(file_path):
                ext = os.path.splitext(filename)[1].lower()
                if ext in image_extensions:
                    image_files.append(file_path)
        
        return image_files
    
    def process_files_in_area(self, prefix, replace_words, select_frame, select_label):
        """处理指定区域中的文件"""
        # 找到对应的区域数据
        area_data = self.find_area_data_by_select_frame(select_frame)
        if not area_data:
            return
            
        folder_path = area_data["selected_path"]
        if not folder_path or not os.path.isdir(folder_path):
            messagebox.showwarning("警告", "请先选择有效的文件夹")
            return
        
        try:
            # 获取所有图片文件
            image_files = self.get_image_files(folder_path)
            total_files = len(image_files)
            
            if total_files == 0:
                self.update_area_status(area_data, "未找到任何图片文件")
                messagebox.showinfo("提示", "未找到任何图片文件")
                return
            
            self.update_area_status(area_data, f"准备处理 {total_files} 个图片文件...")
            self.update_area_progress(area_data, 0)
            self.log_to_area(area_data, f"开始处理文件夹: {folder_path}")
            self.log_to_area(area_data, f"找到 {total_files} 个图片文件")
            
            # 尝试排序文件
            try:
                image_files.sort(key=lambda item: int(re.search(r"\d+", pathlib.Path(item).resolve().stem).group()))
                self.log_to_area(area_data, f"已按数字顺序排序文件")
            except Exception as e:
                self.log_to_area(area_data, f"排序警告: 无法按数字排序，将使用默认顺序 - {str(e)}")
            
            # 重命名文件
            success_count = 0
            for index, file in enumerate(image_files, start=1):
                try:
                    file_path = pathlib.Path(file).resolve()
                    directory = file_path.parent
                    old_name = file_path.name
                    suffix = file_path.suffix
                    
                    # 创建新文件名
                    new_basename = f"{prefix}-{index:03}"
                    for word in replace_words:
                        new_basename = new_basename.replace(word, "-")
                    new_name = f"{new_basename}{suffix}"
                    
                    # 重命名
                    old_full_path = os.path.join(directory, old_name)
                    new_full_path = os.path.join(directory, new_name)
                    
                    # 检查新文件名是否已存在
                    if os.path.exists(new_full_path):
                        self.log_to_area(area_data, f"跳过 {old_name}: 目标文件 {new_name} 已存在")
                        continue
                    
                    os.rename(old_full_path, new_full_path)
                    self.log_to_area(area_data, f"已重命名: {old_name} -> {new_name}")
                    success_count += 1
                    
                except Exception as e:
                    self.log_to_area(area_data, f"重命名失败 {old_name}: {str(e)}")
                
                # 更新进度
                progress = (index / total_files) * 100
                self.update_area_progress(area_data, progress)
            
            self.update_area_progress(area_data, 100)
            self.update_area_status(area_data, f"处理完成: 成功{success_count}个，失败{total_files - success_count}个")
            messagebox.showinfo("完成", f"{area_data['status_label']['text'].split('处理区')[0]}处理完成:\n成功{success_count}个\n失败{total_files - success_count}个")
            
        except Exception as e:
            error_msg = f"处理时出错: {str(e)}"
            self.update_area_status(area_data, error_msg)
            self.log_to_area(area_data, error_msg)
            messagebox.showerror("错误", error_msg)

if __name__ == "__main__":
    app = ImageRenamerApp()
    app.mainloop()